
package de.justphil.tcg.tcgandroidclient.network.rest;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import de.justphil.tcg.tcgandroidclient.content.rest.RESTCard;
import de.justphil.tcg.tcgandroidclient.content.rest.RESTCardInstance;
import de.justphil.tcg.tcgandroidclient.content.rest.RESTCreateGameResponse;
import de.justphil.tcg.tcgandroidclient.content.rest.RESTDeck;
import de.justphil.tcg.tcgandroidclient.content.rest.RESTGameReadyResponse;
import de.justphil.tcg.tcgandroidclient.content.rest.RESTGeoCard;
import de.justphil.tcg.tcgandroidclient.util.GeoCalculation;
import de.justphil.tcg.tcgandroidclient.util.TCGLog;

public class RESTDecoder {
	
	static RESTCard decodeCard(String dataStr) {
	
		TCGLog.d(new Object[] {
				"Decoding RESTCard: ", dataStr });
		try {
			JSONObject dataJson = new JSONObject(dataStr);
			JSONObject cardJson = dataJson.getJSONObject("d");
			String name = cardJson.getString("name");
			int life = cardJson.getInt("l");
			int attack = cardJson.getInt("at");
			int defense = cardJson.getInt("d");
			int agility = cardJson.getInt("ag");
			JSONArray propertyTypesJson = cardJson.getJSONArray("pIds");
			int[] propertyTypes = new int[propertyTypesJson.length()];
			for (int i = 0; i < propertyTypesJson.length(); i++) {
				propertyTypes[i] = propertyTypesJson.getInt(i);
			}
			return new RESTCard(life, attack, defense, agility, name, propertyTypes);
		}
		catch (JSONException e) {
			throw new IllegalArgumentException("Error parsing a RESTCard from Json: "
					+ e.getMessage());
		}
	}
	
	static List<RESTCardInstance> decodeCardInstances(String bodyStr) {
	
		TCGLog.d(new Object[] {
				"Decoding Reposotory: ", bodyStr });
		List<RESTCardInstance> repository = new ArrayList<RESTCardInstance>();
		try {
			JSONArray cardsJson = new JSONObject(bodyStr).getJSONArray("d");
			JSONObject cardJson;
			for (int i = 0; i < cardsJson.length(); i++) {
				cardJson = cardsJson.getJSONObject(i);
				repository
						.add(new RESTCardInstance(cardJson.getLong("id"), cardJson.getInt("card")));
			}
		}
		catch (JSONException e) {
			throw new IllegalArgumentException("Error parsing Json Message: " + bodyStr);
		}
		return repository;
	}
	
	static List<RESTDeck> decodeDecks(String bodyStr) {
	
		TCGLog.d(new Object[] {
				"Decoding Decks: ", bodyStr });
		List<RESTDeck> decks = new LinkedList<RESTDeck>();
		try {
			JSONArray decksJson = new JSONObject(bodyStr).getJSONArray("d");
			JSONObject deckJson;
			String name;
			JSONArray cardIdsJson;
			long[] cardIds;
			long deckId;
			for (int i = 0; i < decksJson.length(); i++) {
				deckJson = decksJson.getJSONObject(i);
				name = deckJson.getString("name");
				deckId = deckJson.getLong("id");
				cardIdsJson = deckJson.getJSONArray("cardInstances");
				cardIds = new long[cardIdsJson.length()];
				for (int j = 0; j < cardIds.length; j++) {
					cardIds[j] = cardIdsJson.getLong(j);
				}
				decks.add(new RESTDeck(deckId, cardIds, name));
			}
		}
		catch (JSONException e) {
			throw new IllegalArgumentException("Error parsing Json Message: " + bodyStr);
		}
		return decks;
	}
	
	public static RESTCreateGameResponse decodeCreateGameResult(String bodyStr) {
	
		TCGLog.d(new Object[] {
				"Decoding CreateGameResult: ", bodyStr });
		RESTCreateGameResponse response;
		try {
			JSONObject responseJson = new JSONObject(bodyStr).getJSONObject("d");
			response =
					new RESTCreateGameResponse(responseJson.getString("otp"),
							responseJson.getInt("pollInterval"));
		}
		catch (JSONException e) {
			throw new IllegalArgumentException("Error parsing Json Message: " + bodyStr);
		}
		return response;
	}
	
	public static RESTGameReadyResponse decodePlayerJoinedResponse(String bodyStr) {
	
		return decodeGameReadyResponse(bodyStr);
	}
	
	public static RESTGameReadyResponse decodeGameReadyResponse(String bodyStr) {
	
		/* { "d" : { "gameId":1, "wsUri":"ws://localhost:8888/game", "playerOtp":"472a9d" } } */
		TCGLog.d(new Object[] {
				"Decoding CreateGameResult: ", bodyStr });
		RESTGameReadyResponse response;
		try {
			JSONObject responseJson = new JSONObject(bodyStr).getJSONObject("d");
			response =
					new RESTGameReadyResponse(responseJson.getString("playerOtp"),
							responseJson.getString("wsUri"), responseJson.getLong("gameId"));
		}
		catch (JSONException e) {
			throw new IllegalArgumentException("Error parsing Json Message: " + bodyStr);
		}
		return response;
	}
	
	public static RESTGameReadyResponse decodeJoinResponse(String bodyStr) {
	
		return decodeGameReadyResponse(bodyStr);
	}
	
	public static String decodeMessage(String bodyStr) {
	
		TCGLog.d(new Object[] {
				"Decoding Message: ", bodyStr });
		try {
			return new JSONObject(bodyStr).getString("m");
		}
		catch (JSONException e) {
			throw new IllegalArgumentException("Error parsing Json Message: " + bodyStr);
		}
	}
	
	public static long decodeLogInResponse(String bodyStr) {
	
		/* { "d" : {"userId":4} } */
		TCGLog.d(new Object[] {
				"Decoding Error Message: ", bodyStr });
		try {
			return new JSONObject(bodyStr).getJSONObject("d").getLong("userId");
		}
		catch (JSONException e) {
			throw new IllegalArgumentException("Error parsing Json Message: " + bodyStr);
		}
	}
	
	public static List<RESTGeoCard> decodeGeoResponse(String bodyStr) {
	
		/* { "d" : [ {"id":107,"lat":51.48934458421732,"lon":7.012534110911336,"card":3},
		 * {"id":128,"lat":51.445747450948765,"lon":7.068043026256827,"card":5} ] } */
		List<RESTGeoCard> cards = new ArrayList<RESTGeoCard>();
		try {
			JSONArray cardsJson = new JSONObject(bodyStr).getJSONArray("d");
			for (int i = 0; i < cardsJson.length(); i++) {
				JSONObject cardJson = cardsJson.getJSONObject(i);
				double latitude = cardJson.getDouble("lat");
				double longitude = cardJson.getDouble("lon");
				cards.add(new RESTGeoCard(cardJson.getLong("id"), cardJson.getInt("card"),
						latitude, longitude));
			}
		}
		catch (Exception e) {
			throw new IllegalArgumentException("Error parsing Json Message: " + bodyStr + "\n"
					+ e.getMessage());
		}
		return cards;
	}
}
